package iot

import (
	"strings"
	"time"

	"gorm.io/gorm"

	"github.com/suifengtec/gocoord"

	"github.com/fakeyanss/jt808-server-go/internal/iot/model"
	log2 "github.com/fakeyanss/jt808-server-go/pkg/log"
)

var GlobalDeviceManager *manager

type manager struct {
	DB *gorm.DB
}

func MustInitManager() {
	m := &manager{}
	m.DB = mustInitPgsql()

	GlobalDeviceManager = m
}

func (m *manager) OnStat(phone string, stat *model.BaseDeviceStat) {
	now := time.Now().Format("2006-01-02 15:04:05")
	log2.Info("location stat", log2.String("phone", phone),
		log2.Any("longitude", stat.Longitude),
		log2.Any("latitude", stat.Latitude),
		log2.String("time", now),
	)

	if !strings.HasPrefix(phone, "0") {
		log2.Error("invalid phone number", log2.String("phone", phone))
	}

	sn := strings.TrimPrefix(phone, "0")

	gcj02Lon, gcj02Lat := m.wgs84ToGCJ02(stat.Longitude, stat.Latitude)
	bd09Lon, bd09Lat := m.wgs84ToBD09(stat.Longitude, stat.Latitude)

	err := model.StoreLocation(GlobalDeviceManager.DB, &model.Location{
		SN:             sn,
		Time:           now,
		WGS84Longitude: stat.Longitude,
		WGS84Latitude:  stat.Latitude,
		GCJ02Longitude: gcj02Lon,
		GCJ02Latitude:  gcj02Lat,
		BD09Longitude:  bd09Lon,
		BD09Latitude:   bd09Lat,
	})
	if err != nil {
		log2.Error("store location error", log2.String("phone", phone))
	}
}

func (m *manager) wgs84ToGCJ02(wgs84Lon, wgs84Lat float64) (float64, float64) {
	p := gocoord.WGS84ToGCJ02(gocoord.Position{
		Lon: wgs84Lon,
		Lat: wgs84Lat,
	})
	return p.Lon, p.Lat
}

func (m *manager) wgs84ToBD09(wgs84Lon, wgs84Lat float64) (float64, float64) {
	p := gocoord.WGS84ToBD09(gocoord.Position{
		Lon: wgs84Lon,
		Lat: wgs84Lat,
	})
	return p.Lon, p.Lat
}

func (m *manager) ListLocation(sn, start, end string) ([]*model.Location, error) {
	return model.ListLocation(GlobalDeviceManager.DB, sn, start, end)
}

func (m *manager) FindLastBySN(sn string) (*model.Location, error) {
	return model.FindLastBySN(GlobalDeviceManager.DB, sn)
}

func (m *manager) FindLastBySNList(list []string) ([]*model.Location, error) {
	return model.FindLastBySNList(GlobalDeviceManager.DB, list)
}
